#!/bin/bash
# napisane przez Kamil Cukrowski data: 5.01.2015 ! licensed under BEERWARE :D


# --------------- functions ----------
. ./functions.sh
# ------------------ zbierz adres ip, ktory jest na interface ------------------
if is_yes "$STATIC_IP"; then
	[ -z "$EXTERNAL_IP" ] && \
		EXTERNAL_IP="$(ifconfig "$EXTERNAL_INTERFACE" | grep inet | awk '{print $2}')"
	[ -z "$EXTERNAL_IP" ] && \
	{
		echo 'External ip not found! Exiting.'
		exit 1
	}
	FROM_EXTERNAL_IP="-s $EXTERNAL_IP/32"
	TO_EXTERNAL_IP="-d $EXTERNAL_IP/32"
fi
# -------------- KERNEL ------------

# http://www.tty1.net/blog/2007/iptables-firewall_en.html
echo 1 > /proc/sys/net/ipv4/tcp_syncookies                          # if 1, enable syn cookies (prevent against the common 'syn flood attack')
echo 1 > /proc/sys/net/ipv4/ip_forward                              # if 0, disable Packet forwarning between interfaces
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts             # if 1, ignore all ICMP ECHO and TIMESTAMP requests sent to it via broadcast/multicast
echo 0 > /proc/sys/net/ipv4/conf/all/log_martians                   # if 1, log packets with impossible addresses to kernel log
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses       # if 1, disable logging of bogus responses to broadcast frames
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter                      # if 1, do source validation by reversed path (Recommended option for single homed hosts)
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects                 # if 0, don't send redirects
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route            # if 0, don't accept packets with SRR option
# --------------------------------
modprobe ip_tables
# --------------------------------
set -x
# ------------- flush iptables -----------
iptables --flush
iptables --delete-chain
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

######################## FILTER begin #########################
# zrodla z ktorych korzystalem
# http://newartisans.com/2007/09/neat-tricks-with-iptables/
# https://wiki.archlinux.org/index.php/simple_stateful_firewall

# polaczenia juz istniejace -> accept
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# wszystkie inne interfacy niz zewnetrzny -> accept (dlatego potem nie pisze juz -i INTERFACE)
iptables -A INPUT ! -i "$EXTERNAL_INTERFACE" -j ACCEPT
# Drop invalid packets
iptables -A INPUT -m state --state INVALID -j DROP

if is_yes "$DROP_SPOOFED"; then
	# http://newartisans.com/2007/09/neat-tricks-with-iptables/
	# Reject packets from RFC1918 class networks (i.e., spoofed)
	# drop spoofed packets (i.e. packets with local source addresses coming from outside etc.), mark as Bad Guy
	iptables -A INPUT -s 10.0.0.0/8     -j DROP
	iptables -A INPUT -s 169.254.0.0/16 -j DROP
	iptables -A INPUT -s 172.16.0.0/12  -j DROP
	iptables -A INPUT -s 127.0.0.0/8    -j DROP
	
	iptables -A INPUT -s 224.0.0.0/4      -j DROP
	iptables -A INPUT -d 224.0.0.0/4      -j DROP
	iptables -A INPUT -s 240.0.0.0/5      -j DROP
	iptables -A INPUT -d 240.0.0.0/5      -j DROP
	iptables -A INPUT -s 0.0.0.0/8        -j DROP
	iptables -A INPUT -d 0.0.0.0/8        -j DROP
	iptables -A INPUT -d 239.255.255.0/24 -j DROP
	iptables -A INPUT -d 255.255.255.255  -j DROP
fi

##################### icmp ###############
if is_yes "$ICMP_DROP"; then
	iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
else
	# limit pings per address
	# https://wiki.archlinux.org/index.php/simple_stateful_firewall#Block_ping_request
	iptables -A INPUT -p icmp --icmp-type echo-request \
		-m recent --name ping_limiter --set
	iptables -A INPUT -p icmp --icmp-type echo-request \
		-m recent --name ping_limiter --update --hitcount 6 --seconds 4 -j DROP
	iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
fi

#### utworzenie dwoch chainow TCP i UDP i przekierowanie do nich TCP i UDP z odpowiednimi flagami
# https://wiki.archlinux.org/index.php/simple_stateful_firewall
iptables -N TCP
iptables -N UDP
iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
iptables -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP

if is_yes "$MYSTERION"; then
	# Drop bogus TCP packets
	iptables -A TCP -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
	iptables -A TCP -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
	
	# Drop excessive RST packets to avoid SMURF attacks, by given the
	# next real data packet in the sequence a better chance to arrive first.
	iptables -A TCP -p tcp -m tcp --tcp-flags RST RST \
	    -m limit --limit 2/second --limit-burst 2 -j ACCEPT
	
	# Protect against SYN floods by rate limiting the number of new
	# connections from any host to 20 per second.  This does *not* do rate
	# limiting overall, because then someone could easily shut us down by
	# saturating the limit.
	iptables -A TCP -m state --state NEW -p tcp -m tcp --syn \
	    -m recent --name synflood --set
	iptables -A TCP -m state --state NEW -p tcp -m tcp --syn \
	    -m recent --name synflood --update --seconds 1 --hitcount 20 -j DROP
fi
	
if is_yes "$BLOCK_SAMBA_PORT"; then
	# blokuj kazdego na caly dzien, kto sie sprobuje polaczyc z portem 139 !!
	
	# Anyone who tried to portscan us is locked out for an entire day.
	iptables -A INPUT   -m recent --name portscan --rcheck --seconds 86400 -j DROP
	#iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP
	
	# Once the day has passed, remove them from the portscan list
	iptables -A INPUT   -m recent --name portscan --remove
	#iptables -A FORWARD -m recent --name portscan --remove
	
	# These rules add scanners to the portscan list, and log the attempt.
	# !! port 139 czyli dla samba jest zamknięty na zewnątrzn
	iptables -A INPUT   -p tcp -m tcp --dport 139 \
	    -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
	iptables -A INPUT   -p tcp -m tcp --dport 139 \
	    -m recent --name portscan --set -j DROP
	
	#iptables -A FORWARD -p tcp -m tcp --dport 139 \
	#    -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
	#iptables -A FORWARD -p tcp -m tcp --dport 139 \
	#    -m recent --name portscan --set -j DROP	
fi


############################## SSH #################################
if is_yes "$SSH_FAIL2BAN"; then
#	iptables -N fail2ban-IMAP
#	iptables -N fail2ban-SSH
#	iptables -A INPUT -p tcp -m multiport --dports 993 -j fail2ban-IMAP
#	iptables -A INPUT -p tcp -m tcp --dport 22 -j fail2ban-SSH
#	iptables -A fail2ban-IMAP -j RETURN
#	iptables -A fail2ban-SSH -j RETURN
	sleep 0
fi
if is_yes "$SSH_HITCOUNT"; then
	# utwórz chain IN_SSH i uwalaj za duzo polaczen
	iptables -N IN_SSH
	iptables -A INPUT -p tcp --dport $SSH_PORT -m conntrack --ctstate NEW -j IN_SSH
	iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 15 -j DROP
	#iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 6 --seconds 1800 -j DROP 
	iptables -A IN_SSH -m recent --name sshbf --set -j ACCEPT
fi

############################ OPEN PORTS ################################
if [[ -n "$OPEN_PORTS" ]]; then
	iptables -A UDP -p udp -m multiport --dport $OPEN_PORTS -j ACCEPT
	iptables -A TCP -p tcp -m multiport --dport $OPEN_PORTS -j ACCEPT
fi
if [[ -n "$OPEN_PORTS2" ]]; then
	iptables -A UDP -p udp -m multiport --dport $OPEN_PORTS2 -j ACCEPT
	iptables -A TCP -p tcp -m multiport --dport $OPEN_PORTS2 -j ACCEPT
fi
if [[ -n "$OPEN_PORTS_TCP" ]]; then
	iptables -A TCP -p tcp -m multiport --dport $OPEN_PORTS_TCP -j ACCEPT
fi
if [[ -n "$OPEN_PORTS_UDP" ]]; then
	iptables -A UDP -p udp -m multiport --dport $OPEN_PORTS_UDP -j ACCEPT
fi

##### block TCP SYN scans  https://wiki.archlinux.org/index.php/simple_stateful_firewall
iptables -A TCP -p tcp -m recent --update --seconds 60 \
	--name TCP-PORTSCAN -j REJECT --reject-with tcp-rst
iptables -A INPUT -p tcp -m recent --set --name TCP-PORTSCAN \
	-j REJECT --reject-with tcp-rst
##### block UDP scans  https://wiki.archlinux.org/index.php/simple_stateful_firewall
iptables -A UDP -p udp -m recent --update --seconds 60 \
	--name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -p udp -m recent --set --name UDP-PORTSCAN \
	-j REJECT --reject-with icmp-port-unreachable

##### final rules
iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

if is_yes "$MASQ_LOCAL_NET"; then
	if [[ ! -z "LOCAL_IP" ]] ; then
		for MOD in ip_nat_ftp ipt_MASQUERADE ip_conntrack_ftp ipt_REJECT; do
			/sbin/modprobe $MOD
		done
		# iptables -t nat -A PREROUTING -i "$EXTERNAL_INTERFACE" -d "$LOCAL_NET" -j DROP
		# iptables -t nat -A PREROUTING -i "$EXTERNAL_INTERFACE" -s "$LOCAL_NET" -j DROP
		# iptables -t nat -A POSTROUTING -o "$EXTERNAL_INTERFACE" -d "$LOCAL_NET" -j DROP
		if is_yes "$STATIC_IP"; then
			iptables -t nat -A POSTROUTING -s "$LOCAL_NET" \
				-o "$EXTERNAL_INTERFACE" -j SNAT --to "$EXTERNAL_IP"
		else
			iptables -t nat -A POSTROUTING -s "$LOCAL_NET" \
				-o "$EXTERNAL_INTERFACE" -j MASQUERADE
		fi
	fi
fi

set -x
# iptables-save
